package 中等.搜索.广度优先搜索;

import java.util.ArrayDeque;
import java.util.Deque;

/**
 * 给定一个二叉树
 * struct Node {
 * int val;
 * Node *left;
 * Node *right;
 * Node *next;
 * }
 * 填充它的每个 next 指针，让这个指针指向其下一个右侧节点。如果找不到下一个右侧节点，则将 next 指针设置为 NULL。
 * 初始状态下，所有 next 指针都被设置为 NULL。
 * 进阶：
 * 你只能使用常量级额外空间。
 * 使用递归解题也符合要求，本题中递归程序占用的栈空间不算做额外的空间复杂度。
 * <p>
 * 来源：力扣（LeetCode）
 * 链接：https://leetcode.cn/problems/populating-next-right-pointers-in-each-node-ii
 */
public class 填充每个节点的下一个右侧节点指针II_117 {

    public static void main(String[] args) {

    }

    /**
     * 广度优先搜索+队列
     */
    public Node connect(Node root) {
        if (root == null) return null;
        Deque<Node> queue = new ArrayDeque<>();
        queue.addLast(root);

        while (!queue.isEmpty()) {
            Node preNode = null;
            int size = queue.size();
            while (size-- > 0) {
                Node node = queue.pollFirst();
                node.next = preNode;

                if (node.right != null) {
                    queue.addLast(node.right);
                }
                if (node.left != null) {
                    queue.addLast(node.left);
                }
                preNode = node;
            }
        }
        return root;
    }

    /**
     * TODO 广度优先搜索+链表
     * 每一层节点都可以看做一个链表
     */

    static class Node {
        int val;
        Node left;
        Node right;
        Node next;
    }

    public Node connect2(Node root) {
        if (root == null) return null;
        Deque<Node> queue = new ArrayDeque<>();
        queue.addLast(root);

        while (!queue.isEmpty()) {
            int size = queue.size();

            Node preNode = new Node();
            while (size-- > 0) {

                Node curNode = queue.pollFirst();
                preNode.next = curNode;
                preNode = curNode;

                if (curNode.left != null) {
                    queue.addLast(curNode.left);
                }
                if (curNode.right != null) {
                    queue.addLast(curNode.right);
                }
            }
        }
        return root;
    }

}
